昨天提到了Middleware的使用方式,今天來看看其他的使用方式
所謂的基於約定有點像是鴨子型別的概念
當滿足約定的話,我們就能把它視為一個中介軟體
讓我們來看看一個符合中介軟體的約定有哪些
這是一個驗證http request是否為有效的middleware
細節我是隨便寫的,用了MD5所以不要直接call來用
public class SignatureMiddleware
{
private readonly RequestDelegate _next;
public SignatureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var request = context.Request;
var response = context.Response;
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
var _ = await request.Body.ReadAsync(buffer);
var bodyAsText = Encoding.UTF8.GetString(buffer);
request.Body = new MemoryStream(buffer);
var signature = request.Headers["X-Signature"];
var timestamp = request.Headers["X-Signature-Timestamp"];
var isValid = Verify(bodyAsText, signature, timestamp);
if (!isValid)
{
response.StatusCode = 401;
return;
}
await _next.Invoke(context);
}
private static bool Verify(string body, string signature, string timestamp)
{
var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(body + timestamp));
var hashString = BitConverter.ToString(hash).Replace("-", "").ToLower();
return hashString == signature;
}
}
可以看到這個middleware滿足我所說的條件
然後可以在program.cs
中依照想要的位置
使用app.UseMiddleware
插入這個middleware
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseMiddleware<SignatureMiddleware>();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
await app.RunAsync();
**
另外基於約定的Middleware是應用程式啟動時即建立實體,他在某種程度上類似singleton
因此雨果要使用,其他註冊為Scope的服務並不能在建構式中注入
而要在Invoke方法中注入
**
public async Task InvokeAsync(HttpContext context, IMyService)
{
// DoSomething
}
除了這種基於約定的middleware外
也可以選擇實作IMiddleware
實作IMiddleware
的Middleware
是由IMiddlewareFactory
所建立的
相比基於約定的中介軟體
他是
public class SignatureMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var request = context.Request;
var response = context.Response;
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
var _ = await request.Body.ReadAsync(buffer);
var bodyAsText = Encoding.UTF8.GetString(buffer);
request.Body = new MemoryStream(buffer);
var signature = request.Headers["X-Signature-"];
var timestamp = request.Headers["X-Signature-Timestamp"];
var isValid = Verify(bodyAsText, signature, timestamp);
if (!isValid)
{
response.StatusCode = 401;
return;
}
await next.Invoke(context);
}
private static bool Verify(string body, string signature, string timestamp)
{
var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(body + timestamp));
var hashString = BitConverter.ToString(hash).Replace("-", "").ToLower();
return hashString == signature;
}
}
使用上基本上跟基於約定的Middleware相同
app.UseMiddleware<SignatureMiddleware>();